#include <retro.h>
#include "retro.creator.h"

using namespace Retro::Creator::Dialog;

DialogBase::DialogBase() :
  gdiFont(CreateFont(
    16, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
    OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY,
    VARIABLE_PITCH, _T("Arial"))),
  gdipFont(GetDC(NULL), gdiFont)
{
}

DialogBase::~DialogBase()
{
  mLayout.destroy();
}

BOOL    DialogBase::create(
  LPCTSTR title,
  INT     width,
  HWND    owner,
  BOOL    sizeable)
{
  return Window::create(title,
    (sizeable ? WS_THICKFRAME : WS_DLGFRAME) |
    WS_CAPTION | WS_SYSMENU |
    WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
    WS_EX_DLGMODALFRAME,
    0, 0, width, 0, owner);
}

VOID    DialogBase::onEraseBackground(Event::EraseBackgroundEvent& iEvent)
{
  Gdip::Graphics(*this).Clear(RETRO_DIALOG_BKCOLOR);
  *iEvent.handled = TRUE;
}

VOID    DialogBase::onSize(Event::SizeEvent& iEvent)
{
  mLayout.doLayout();
}

VOID    DialogBase::onSizing(Event::SizingEvent& iEvent)
{
  Geom::Size wSize;
  mLayout.calcSize(wSize);

  adjustMinimumSize(300, wSize.cy, iEvent.sizeEdge, iEvent.rect);
}

VOID    DialogBase::onCreate(Event::WndCreateEvent& iEvent)
{
  Geom::Rect wRect = { };

  mLayout = getHandle();
  mLayout.padding.setAll(10);

  onLoad();
  
  mLayout.calcSize(wRect.rightBottom);

  adjustRect(wRect);
  setHeight(wRect.getHeight());

  mLayout.doLayout();
}

VOID    DialogBase::onDestroy()
{
  DeleteObject(gdiFont);
}

VOID    DialogBase::onShowWindow(Event::ShowWindowEvent& iEvent)
{
  if (iEvent.shown)
  {
    Geom::Rect parent = Geom::Rect::fromWindow(getOwner());
    Geom::Rect client = Geom::Rect::fromClient(*this);

    setPos(parent.leftTop + 
      Geom::Point(parent.getSize() - client.getSize()) / 2);

    setResult(DialogCancel);
  }
  else
  {
    onUnload();
  }

  Window::onShowWindow(iEvent);
}

VOID    DialogBase::addSeparator(
  Separator   &separator)
{
  separator.create(*this);
  separator.setBackColor(RETRO_DIALOG_BKCOLOR);

  mLayout.addTop(14, separator);
}

VOID    DialogBase::addEdit(
  HWND        &hEdit,
  Label       &label,
  PCTSTR      text)
{
  label.create(*this, text);
  label.setFont(getGdipFont());
  label.setAlignY(Gdip::StringAlignmentNear);
  label.setBackColor(RETRO_DIALOG_BKCOLOR);

  hEdit = CreateWindowEx(
    WS_EX_LEFT | WS_EX_CLIENTEDGE | WS_EX_CONTEXTHELP,
    WC_EDIT, _T(""), WS_CHILD | WS_VISIBLE | WS_TABSTOP |
    ES_LEFT | ES_WANTRETURN | ES_AUTOHSCROLL,
    0, 0, 0, 0, *this, NULL, getInstance(), NULL);

  SetWindowFont(hEdit, getGdiFont(), FALSE);
  SendMessage(hEdit, EM_SETLIMITTEXT, RETRO_MAXNAME - 1, 0);

  mLayout.addTop(18, label);
  mLayout.addTop(23, hEdit)->margins.bottom = 2;
}

LayoutElement*  DialogBase::addNumeric(
  HWND        &hUpDown,
  HWND        &hEdit,
  Label       &label,
  PCTSTR      text,
  INT         min,
  INT         max,
  INT         val)
{
  hEdit = CreateWindowEx(
    WS_EX_LEFT | WS_EX_CLIENTEDGE | WS_EX_CONTEXTHELP,
    WC_EDIT, _T(""), WS_CHILD | WS_TABSTOP |
    ES_NUMBER | ES_LEFT | ES_AUTOHSCROLL | ES_WANTRETURN,
    0, 0, 0, 0, *this, NULL, getInstance(), NULL);
  hUpDown = CreateWindowEx(
    WS_EX_LEFT | WS_EX_LTRREADING, UPDOWN_CLASS, _T(""),
    WS_CHILD | UDS_ARROWKEYS | UDS_HOTTRACK | UDS_SETBUDDYINT,
    0, 0, 0, 0, *this, NULL, getInstance(), NULL);

  SetWindowFont(hEdit, getGdiFont(), FALSE);

  label.create(*this, text);
  label.setFont(getGdipFont());
  label.setBackColor(RETRO_DIALOG_BKCOLOR);

  SendMessage(hUpDown, UDM_SETBUDDY, (WPARAM)hEdit, 0);
  SendMessage(hUpDown, UDM_SETRANGE32, min, max);
  SendMessage(hUpDown, UDM_SETPOS32, 0, val);

  LayoutElement* panel = mLayout.addTop(23);

  panel->margins.setVert(2);
  panel->addRight(20, hUpDown);
  panel->addRight(RETRO_DIALOG_RIGHTSIZE - 20, hEdit);
  panel->addLeft(RETRO_DIALOG_LEFTSIZE, label);

  return panel;
}

LayoutElement*  DialogBase::addPath(
  HWND        &hEdit,
  Label       &label,
  Button      &button,
  PCTSTR      text,
  UINT        id)
{
  hEdit = CreateWindowEx(
    WS_EX_LEFT | WS_EX_CLIENTEDGE,
    WC_EDIT, _T(""), WS_CHILD | WS_VISIBLE | WS_TABSTOP |
    ES_LEFT | ES_WANTRETURN | ES_AUTOHSCROLL,
    0, 0, 0, 0, *this, NULL, getInstance(), NULL);

  label.create(*this, text);
  label.setFont(getGdipFont());
  label.setBackColor(RETRO_DIALOG_BKCOLOR);

  button.create(*this, _T("..."), WS_TABSTOP);
  button.setID(id);
  button.setBackColor(RETRO_DIALOG_BKCOLOR);

  SetWindowFont(hEdit, getGdiFont(), FALSE);
  Edit_LimitText(hEdit, MAX_PATH - 1);

  mLayout.addTop(18, label);

  LayoutElement* panel = mLayout.addTop(23);
  
  panel->margins.setVert(2);
  panel->addRight(25, button)->margins.left = 5;
  panel->addFill(hEdit);

  return panel;
}

LayoutElement*  DialogBase::addComboBox(
  HWND        &hCombo,
  Label       &label,
  PCTSTR      text)
{
  label.create(*this, text);
  label.setFont(getGdipFont());
  label.setBackColor(RETRO_DIALOG_BKCOLOR);

  hCombo = CreateWindow(WC_COMBOBOX, _T(""),
    CBS_DROPDOWN | CBS_HASSTRINGS | CBS_DROPDOWNLIST |
    WS_CHILD | WS_OVERLAPPED | WS_VISIBLE | WS_TABSTOP,
    0, 0, 0, 0, *this, NULL, getInstance(), NULL);

  SetWindowFont(hCombo, getGdiFont(), FALSE);

  LayoutElement* panel = mLayout.addTop(23);
  
  panel->margins.setVert(2);
  panel->addLeft(RETRO_DIALOG_LEFTSIZE, label);
  panel->addRight(RETRO_DIALOG_RIGHTSIZE, hCombo);

  return panel;
}

LayoutElement*  DialogBase::addOKCancel(
  Button      &btnOK,
  Button      &btnCancel,
  Separator   &separator)
{
  btnOK.create(*this, _T("OK"), WS_TABSTOP);
  btnOK.setBackColor(RETRO_DIALOG_BKCOLOR);
  btnOK.setForeColor(0x00FF00);
  btnOK.setID(IDOK);

  btnCancel.create(*this, _T("Cancel"), WS_TABSTOP);
  btnCancel.setBackColor(RETRO_DIALOG_BKCOLOR);
  btnCancel.setForeColor(0xFF0000);
  btnCancel.setID(IDCANCEL);

  LayoutElement* pButtons = mLayout.addBottom(30);

  pButtons->margins.top = 2;
  pButtons->addRight(75, btnCancel)->margins.left = 5;
  pButtons->addRight(75, btnOK);

  separator.create(*this);
  separator.setBackColor(RETRO_DIALOG_BKCOLOR);

  mLayout.addBottom(14, separator);

  return pButtons;
}

LayoutElement*  DialogBase::addOK(
  Button      &btnOK,
  Separator   &separator)
{
  btnOK.create(*this, _T("OK"), WS_TABSTOP);
  btnOK.setBackColor(RETRO_DIALOG_BKCOLOR);
  btnOK.setForeColor(0x00FF00);
  btnOK.setID(IDOK);

  LayoutElement* pButtons = mLayout.addBottom(30);

  pButtons->margins.top = 2;
  pButtons->addRight(75, btnOK);

  separator.create(*this);
  separator.setBackColor(RETRO_DIALOG_BKCOLOR);

  mLayout.addBottom(14, separator);

  return pButtons;
}
